package src.gladiatormanager;

import java.awt.Point;
import java.awt.geom.Point2D;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Random;
import org.newdawn.slick.Input;
import org.newdawn.slick.AppGameContainer;
import org.newdawn.slick.BasicGame;
import org.newdawn.slick.Color;
import org.newdawn.slick.GameContainer;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.Image;
import org.newdawn.slick.SlickException;


public class GladiatorManager extends BasicGame {
        private static final int LEVEYS = 600;
        private static final int KORKEUS = 600;
        private final int XRUUTUJA = 20;
        private final int YRUUTUJA = 20;
        private final int RUUDUN_LEVEYS = LEVEYS/XRUUTUJA;
        private final int RUUDUN_KORKEUS = KORKEUS/YRUUTUJA;
        private static final int INFO_LEVEYS = 300;
        private static final int TEKSTI_KORKEUS = 20;
        private final int TILA_PELI_ALKU = 0;
        private final int TILA_PELI = 1;
        private final int TILA_PELI_LOPPU = 2;
        private final int TILA_PELI_ALOITA_UUSI = 3;
        private final int MONTAKO_VALITAAN = 10;
        private final int button_newgame_x = LEVEYS+5;
        private final int button_newgame_y = KORKEUS-25;
                
        private int pelinTila, siirtoVuoro, valittuja;
        private Ruudukko ruudukko;
	private Image ball;
        private Image punainen;
        private Image sininen;
        private Image vihrea;
        private Image tausta;
        private Image button_newgame;
	private Random rand;
        private Input input;
        private double[][] kavelymahdollisuudet;
        private ArrayList<Gladiaattori> gladiaattoriLista = new ArrayList<Gladiaattori>();
	
	public GladiatorManager() {
		super("Gladiator Manager");
	}
        
        
	@Override
	public void init(GameContainer gc) throws SlickException {
                kavelymahdollisuudet = null;
                valittuja = 0;
                ruudukko = new Ruudukko(20, 20);
                pelinTila = TILA_PELI_ALKU;
                siirtoVuoro = Joukkue.PUNAINEN;
                //input = gc.getInput();
                //this.setInput(input);     
                tausta = new Image("tausta.jpg");
                tausta = tausta.getScaledCopy(LEVEYS, KORKEUS);
                punainen = new Image("punainen.jpg");
                punainen.setAlpha((float)0.5);
                sininen = new Image("sininen.jpg");
                sininen.setAlpha((float)0.5);
                vihrea = new Image("vihrea.jpg");
                vihrea.setAlpha((float)0.6);
		ball = new Image("ball.jpeg", Color.white);
                ball = ball.getScaledCopy(RUUDUN_LEVEYS, RUUDUN_KORKEUS);
                button_newgame = new Image("button_newgame.jpg");
                //ball.setAlpha((float)1.0);
                Ruutu r = new Ruutu();
                for (int i = 0; i < 10; i++) {
                    r.setGladiaattori(new Gladiaattori(Joukkue.TYHJA, ball));
                    ruudukko.setRuutu(r, i+5-i%2, 9+i%2);
                    //gladiaattoriLista.add(new Gladiaattori(i%2, i+5-i%2, i%2*19));
                }
	}

	@Override
            
	public void update(GameContainer gc, int delta) throws SlickException {
            if (pelinTila == TILA_PELI_ALOITA_UUSI) {
                pelinTila = TILA_PELI_ALKU;
                gc.reinit();
            }
	}

	@Override
	public void render(GameContainer gc, Graphics g) throws SlickException {
		// Manual clear   
		g.setBackground(Color.darkGray);
                tausta.draw();
                //g.setDrawMode(Graphics.MODE_ALPHA_BLEND);
		//g.drawRect(0.0f, 0.0f, gc.getWidth(), gc.getHeight());
		// Draw ball
                g.setColor(Color.white);
                if (ruudukko.getValittu() != null) {
                    
                }
                //g.drawString("Tänne infoa", leveys+5, 30);
                g.drawString("Player "+siirtoVuoro+" TURN!", 10, KORKEUS);
                button_newgame.draw(button_newgame_x, button_newgame_y);
                Point p = ruudukko.getValittuLocation();
                if (p != null) {
                    Gladiaattori valittuGladiaattori = ruudukko.getValittu().getGladiaattori();
                    if (valittuGladiaattori != null) {
                        valittuGladiaattori.getImage().draw(LEVEYS+5, 5);
                        g.drawString(valittuGladiaattori.toString(), LEVEYS+5, 40);
                    }
                    vihrea.draw((int)p.getX()*RUUDUN_LEVEYS, (int)p.getY()*RUUDUN_KORKEUS);
                    if (pelinTila == TILA_PELI_ALKU){
                        if (valittuGladiaattori.getJoukkue() == Joukkue.TYHJA) {   
                            int y = 0;
                            if (siirtoVuoro == Joukkue.PUNAINEN) y = YRUUTUJA-3;
                            for (int xx = 0; xx < XRUUTUJA; xx++) {
                                for (int yy = y; yy < y+3; yy++) {
                                    if (ruudukko.getRuutu(xx, yy).kaveltava() == true) {
                                        if (siirtoVuoro == Joukkue.PUNAINEN) {
                                            punainen.draw(xx*RUUDUN_LEVEYS, yy*RUUDUN_KORKEUS);
                                        } else {
                                            sininen.draw(xx*RUUDUN_LEVEYS, yy*RUUDUN_KORKEUS);
                                        }
                                    }
                                }
                            }
                            ruudukko.getRuutu(0, 0);
                            if (siirtoVuoro == Joukkue.PUNAINEN) {

                            } else if (siirtoVuoro == Joukkue.SININEN) {

                            }
                        }
                    } else if (valittuGladiaattori.getJoukkue() == siirtoVuoro) {//pelinTILA != TILA_PELI_ALKU
                        g.setColor(Color.black);
                        int x = (int)p.getX();
                        int y = (int)p.getY();
                        //tyhja.draw((int)x*ruudunLeveys, (int)y*ruudunLeveys);
                        if (kavelymahdollisuudet == null) kavelymahdollisuudet = kavelymahdollisuudet(x, y, 5);
                        for (int xx = 0; xx < kavelymahdollisuudet.length; xx++) {
                            for (int yy = 0; yy < kavelymahdollisuudet[xx].length; yy++) {
                                if ((kavelymahdollisuudet[xx][yy] > 0) && (kavelymahdollisuudet[xx][yy] <= 5)) {
                                    if (siirtoVuoro == Joukkue.PUNAINEN) {
                                        punainen.draw((xx+x-5)*RUUDUN_LEVEYS, (yy+y-5)*RUUDUN_LEVEYS);//VARJOSTETAAN RUUTU
                                    } else {
                                        sininen.draw((xx+x-5)*RUUDUN_LEVEYS, (yy+y-5)*RUUDUN_LEVEYS);
                                    }    
                                    DecimalFormat df = new DecimalFormat("#.#");
                                    g.drawString(df.format(kavelymahdollisuudet[xx][yy]), (xx+x-5)*RUUDUN_LEVEYS, (yy+y-5)*RUUDUN_LEVEYS);//PIIRRETÄÄN ETÄISYYDET
                                }
                            }
                        }
                    }
//                    for (int xx = x-5; xx < Math.min(x+6, xRuutuja); xx++) {
//                        for(int yy = y-5; yy < y+6; yy++) {
//                            if (Point2D.distance(x, y, xx, yy) < 6) tyhja.draw((xx)*ruudunLeveys, (yy)*ruudunLeveys);
//                        }
//                    }
                }
                
                
                for (int x = 0; x < XRUUTUJA; x++) {
                    for (int y = 0; y < YRUUTUJA; y++) {
                        Gladiaattori gladiaattori = ruudukko.getRuutu(x, y).getGladiaattori();
                        if (gladiaattori == null) continue;
                        gladiaattori.getImage().draw(x*RUUDUN_LEVEYS, y*RUUDUN_KORKEUS); //PIIRRETÄÄN GLADIAATTORIT
                    }
                }
//                for (int i = 0; i < gladiaattoriLista.size(); i++) {
//                    ball.draw((float)(30*gladiaattoriLista.get(i).getLocation().getX()), (float)(ruudunKorkeus*gladiaattoriLista.get(i).getLocation().getY()));
//                }
                g.setColor(Color.black);
                for(int i = RUUDUN_LEVEYS; i < LEVEYS; i += RUUDUN_LEVEYS) {
                    g.drawLine(i, 0, i, KORKEUS);   //PIIRRETÄÄN RUUDUKKOA
                }
                for(int i = RUUDUN_KORKEUS; i < KORKEUS; i += RUUDUN_KORKEUS) {
                    g.drawLine(0, i, LEVEYS, i);
                }
		//ball.draw(ballPos.x, ballPos.y);
	}
        
        private boolean inBox(final int x, final int y, final int x1, final int y1, final int x2, final int y2) {
            return (((x > x1) && (y > y1)) && ((x < x2) && (y < y2)));
        }
        
        @Override
        public void mousePressed(int button, int x, int y) {  
            System.out.println("Mouse button "+button+" was clicked at "+x+", "+y);
            if (button != 0) return; //Tarkkaillaan nyt vaan left clickejä.
            if (inBox(x, y, button_newgame_x, button_newgame_y, button_newgame_x+button_newgame.getWidth(), button_newgame_y+button_newgame.getHeight())) {
                pelinTila = TILA_PELI_ALOITA_UUSI;
            }
            int xr = (x/RUUDUN_LEVEYS);
            int yr = (y/RUUDUN_LEVEYS);
            if ((xr < XRUUTUJA) && (yr < YRUUTUJA)) {
                System.out.println("Ruutua ("+xr+", "+yr+") clikattiin.");
                if (ruudukko.getRuutu(xr, yr).getGladiaattori() != null) {
                    Point p = ruudukko.getValittuLocation();
                    if ((p != null) && (((int)p.getX() != xr) || ((int)p.getY() != yr))) kavelymahdollisuudet = null;
                    ruudukko.setValittu(xr, yr);
                } else {
                    if (ruudukko.getValittu() == null) return;
                    Gladiaattori g = ruudukko.getValittu().getGladiaattori();
                    if (pelinTila == TILA_PELI_ALKU) {
                        if (g.getJoukkue() != Joukkue.TYHJA) return;
                        if ((siirtoVuoro == Joukkue.PUNAINEN) && (yr > XRUUTUJA-4)) {
                            ruudukko.getValittu().setGladiaattori(null);
                            g.setJoukkue(Joukkue.PUNAINEN);
                            ruudukko.getRuutu(xr, yr).setGladiaattori(g);
                            ruudukko.setValittu(null);
                            siirtoVuoro = Joukkue.SININEN;
                            valittuja++;
                        } else if ((siirtoVuoro == Joukkue.SININEN) && (yr < 3)) {
                            ruudukko.getValittu().setGladiaattori(null);
                            g.setJoukkue(Joukkue.SININEN);
                            ruudukko.getRuutu(xr, yr).setGladiaattori(g);
                            ruudukko.setValittu(null);
                            siirtoVuoro = Joukkue.PUNAINEN;
                            valittuja++;
                        }
                        if (valittuja >= MONTAKO_VALITAAN) pelinTila = TILA_PELI;
                    } else if (siirry(ruudukko.getValittu().getX(), ruudukko.getValittu().getY(), xr, yr, 5) > -1) {
                        if (g.getJoukkue() != siirtoVuoro) return;
                        ruudukko.getValittu().setGladiaattori(null);
                        ruudukko.getRuutu(xr, yr).setGladiaattori(g);
                        ruudukko.setValittu(null);
                        if (siirtoVuoro == Joukkue.PUNAINEN) {
                            siirtoVuoro = Joukkue.SININEN;
                        } else {
                            siirtoVuoro = Joukkue.PUNAINEN;
                        }
                        //ruudukko.vaihdaRuudut(ruudukko.getValittu().getX(), ruudukko.getValittu().getX(), xr, yr);
                    }           
                }
            }
        }
        
        @Override
        public void keyPressed(int key, char c) {
            System.out.println("Key #"+key+" was pressed. Char = "+c);
        }
        
        private double[][] kavelymahdollisuudet(final int aloitusX, final int aloitusY, final int maxdist) {
            ArrayList<Point> pA = new ArrayList<Point>();
            pA.add(new Point(aloitusX, aloitusY));
            double[][] matriisi = new double[maxdist*2+1][maxdist*2+1];
            for (int i = 0; i<pA.size(); i++) {
               for (int x = Math.max(aloitusX-maxdist, (int)pA.get(i).getX()-1); x <= Math.min(aloitusX+maxdist, (int)pA.get(i).getX()+1); x++) {
                   if ((x < 0) || (x >= XRUUTUJA)) continue;
                   for (int y = Math.max(aloitusY-maxdist, (int)pA.get(i).getY()-1); y <= Math.min(aloitusY+maxdist, (int)pA.get(i).getY()+1); y++) {
                        if ((x == (int)pA.get(i).getX()) && (y == (int)pA.get(i).getY()) || ((x == aloitusX) && (y == aloitusY))) continue;
                        if ((y < 0) || (y >= YRUUTUJA)) continue;
                        if (ruudukko.getRuutu(x, y).kaveltava()) {
                            int oldx = (matriisi.length-1)/2+(int)pA.get(i).getX()-aloitusX;
                            int oldy = (matriisi.length-1)/2+(int)pA.get(i).getY()-aloitusY;
                            int newx = (matriisi.length-1)/2+x-aloitusX;
                            int newy = (matriisi.length-1)/2+y-aloitusY;
                            double distToNew = Point2D.distance(oldx, oldy, newx, newy);
                            if ((matriisi[newx][newy] == 0) || (matriisi[newx][newy] > matriisi[oldx][oldy]+distToNew)) {
                                matriisi[newx][newy] = matriisi[oldx][oldy]+distToNew;
                                pA.add(new Point(x, y));
                            }
                        }
                   }                 
               }
            }
//            for (int i = 0; i < matriisi.length; i++) {
//                for (int ii = 0; ii < matriisi.length; ii++) {
//                  System.out.print(Math.round(matriisi[ii][i]));
//                }
//                System.out.println("");
//            }
//            System.out.println("");
//            System.out.println("");
//            System.out.println("");
//            System.out.println("");
            return matriisi;           
        }
        
        private double siirry(final int aloitusX, final int aloitusY, final int lopetusX, final int lopetusY, final int maxdist) {
            if (Point2D.distance(aloitusX, aloitusY, lopetusX, lopetusY) > maxdist) return -1;
            ArrayList<Point> pA = new ArrayList<Point>();
            pA.add(new Point(aloitusX, aloitusY));
            double[][] matriisi = new double[maxdist*2+1][maxdist*2+1];
            for (int i = 0; i<pA.size(); i++) {
               for (int x = Math.max(aloitusX-maxdist, (int)pA.get(i).getX()-1); x <= Math.min(aloitusX+maxdist, (int)pA.get(i).getX()+1); x++) {
                   if ((x < 0) || (x >= XRUUTUJA)) continue;
                   for (int y = Math.max(aloitusY-maxdist, (int)pA.get(i).getY()-1); y <= Math.min(aloitusY+maxdist, (int)pA.get(i).getY()+1); y++) {
                        if ((x == (int)pA.get(i).getX()) && (y == (int)pA.get(i).getY()) || ((x == aloitusX) && (y == aloitusY))) continue;
                        if ((y < 0) || (y >= YRUUTUJA)) continue;
                        if (ruudukko.getRuutu(x, y).kaveltava()) {
                            int oldx = (matriisi.length-1)/2+(int)pA.get(i).getX()-aloitusX;
                            int oldy = (matriisi.length-1)/2+(int)pA.get(i).getY()-aloitusY;
                            int newx = (matriisi.length-1)/2+x-aloitusX;
                            int newy = (matriisi.length-1)/2+y-aloitusY;
                            double distToNew = Point2D.distance(oldx, oldy, newx, newy);
                            if ((matriisi[newx][newy] == 0) || (matriisi[newx][newy] > matriisi[oldx][oldy]+distToNew)) {
                                matriisi[newx][newy] = matriisi[oldx][oldy]+distToNew;
                                if ((lopetusX == newx-maxdist+aloitusX) && (lopetusY == newy-maxdist+aloitusY)) return matriisi[newx][newy];
                                pA.add(new Point(x, y));
                            }
                        }
                   }                 
               }
            }
            return -1;
        } 
        

	public static void main(String[] args) throws SlickException {
		AppGameContainer app = new AppGameContainer(new GladiatorManager());
                app.setShowFPS(true);
		app.setDisplayMode(LEVEYS+INFO_LEVEYS, KORKEUS+TEKSTI_KORKEUS, false);
                //app.setClearEachFrame(true);
		app.setTargetFrameRate(50);
                //app.getInput().addMouseListener(this);
		//app.setVSync(true);
		//app.setClearEachFrame(true);
		app.start();
	}
}